import { exec } from 'child_process';
import { promisify } from 'util';
import path from 'path';
import fs from 'fs';
import crypto from 'crypto';
import archiver from 'archiver';
import { ConfigModel } from '../models/Config';

let execAsync = promisify(exec);

export interface NginxConfigInfo {
  name: string;
  content: string;
  file_path: string;
  servers: ServerConfig[];
  upstreams: UpstreamConfig[];
}

export interface ServerConfig {
  server_name: string[];
  listen: number[];
  ssl: boolean;
  ssl_certificate?: string;
  ssl_certificate_key?: string;
  ssl_session_timeout?: string;
  ssl_ciphers?: string;
  ssl_protocols?: string;
  ssl_prefer_server_ciphers?: boolean;
  error_page?: { [key: string]: string };
  includes?: string[];
  locations: LocationConfig[];
  rewrites?: RewriteRule[];
  access_log?: string | 'off';
  error_log?: string | 'off';
  root?: string;
  return?: RedirectConfig;
}

export interface LocationConfig {
  path: string;
  modifier?: string;
  proxy_pass?: string;
  root?: string;
  index?: string[];
  proxy_headers?: Array<{ name: string; value: string }>;
  proxy_connect_timeout?: string;
  proxy_read_timeout?: string;
  proxy_send_timeout?: string;
  proxy_buffer_size?: string;
  proxy_buffers?: string;
  proxy_busy_buffers_size?: string;
  client_max_body_size?: string;
  client_body_buffer_size?: string;
  includes?: string[];
  add_header?: { [key: string]: string };
  try_files?: string[];
  access_log?: string | 'off';
  error_log?: string | 'off';
  return?: RedirectConfig;
  rewrites?: RewriteRule[];
}

export interface SSLCertInfo {
  domain: string;
  cert_path: string;
  key_path: string;
  server_name: string[];
  listen_port: number;
  ssl_protocols?: string;
  ssl_ciphers?: string;
  ssl_prefer_server_ciphers?: boolean;
  ssl_session_timeout?: string;
  ssl_session_cache?: string;
  ssl_stapling?: boolean;
  ssl_stapling_verify?: boolean;
  ssl_trusted_certificate?: string;
  status: 'valid' | 'expired' | 'error' | 'unknown';
  not_before?: string;
  not_after?: string;
  issuer?: string;
}

export interface UpstreamConfig {
  name: string;
  servers: UpstreamServer[];
}

export interface UpstreamServer {
  address: string;
  weight?: number;
  backup?: boolean;
  down?: boolean;
  max_fails?: number;
  fail_timeout?: string;
  comment?: string;
}

export interface ProxyHeader {
  name: string;
  value: string;
}

export interface RewriteRule {
  pattern: string;
  replacement: string;
  flag?: string;
}

export interface RedirectConfig {
  code: number;
  url: string;
}

export interface NginxConfig {
  servers: ServerConfig[];
  upstreams: UpstreamConfig[];
  events?: {
    worker_connections?: number;
    [key: string]: any;
  };
  http?: {
    include?: string[];
    default_type?: string;
    charset?: string;
    sendfile?: string;
    keepalive_timeout?: number;
    gzip?: string;
    gzip_static?: string;
    gzip_comp_level?: number;
    gzip_min_length?: number;
    gzip_types?: string[];
    [key: string]: any;
  };
  worker_processes?: string;
  pid?: string;
  error_log?: string;
  access_log?: string;
  user?: string;
  [key: string]: any;
}

export class NginxUtil {
  private static nginxExec = process.env.NGINX_EXEC || 'nginx';
  public static nginxCwd = process.env.NGINX_CWD || '';
  public static nginxConfdDir = process.env.NGINX_CONF_DIR || 'conf.d';
  private static nginxReloadCmd = process.env.NGINX_RELOAD_CMD || `${this.nginxExec} -s reload`;
  public static isDockerized = false;
  private static dockerContainerName = '';
  private static dockerHostPath = '';
  private static dockerContainerPath = '';
  private static dockerHostLogPath = '';
  private static dockerContainerLogPath = '';
  private static dockerHostSslPath = '';
  private static dockerContainerSslPath = '';

  public static async getNginxVersion(): Promise<string> {
    if (this.isDockerized) {
      const { stdout, stderr } = await execAsync(`docker exec ${this.dockerContainerName} nginx -v`);
      const version = stderr || stdout;
      return version.trim();
    } else {
      const { stdout, stderr } = await execAsync(`${this.nginxExec} -v`);
      const version = stderr || stdout;
      return version.trim();
    }
  }

  public static async updateEnv() {
    const config = await ConfigModel.getSystemConfig();
    if (config) {
      this.nginxExec = config.nginxExec || 'nginx';
      this.nginxCwd = config.nginxCwd || path.dirname(this.nginxExec) || '';
      this.nginxConfdDir = config.nginxConfDir || 'conf.d';
      this.isDockerized = config.isDockerized || false;
      this.dockerContainerName = config.dockerContainerName || '';
      this.dockerHostPath = config.dockerHostPath || '';
      this.dockerContainerPath = config.dockerContainerPath || '';
      this.dockerHostLogPath = config.dockerHostLogPath || '';
      this.dockerContainerLogPath = config.dockerContainerLogPath || '';
      this.dockerHostSslPath = config.dockerHostSslPath || '';
      this.dockerContainerSslPath = config.dockerContainerSslPath || '';

      if (this.isDockerized) {
        this.nginxReloadCmd = `docker exec ${this.dockerContainerName} ${this.nginxExec} -s reload`;
      } else {
        this.nginxReloadCmd = `${this.nginxExec} -s reload`;
      }
    }
    console.log('更新 nginx 配置：');
    console.log('nginxExec', this.nginxExec);
    console.log('nginxCwd', this.nginxCwd);
    console.log('nginxConfdDir', this.nginxConfdDir);
    console.log('nginxReloadCmd', this.nginxReloadCmd);
    console.log('isDockerized', this.isDockerized);
    if (this.isDockerized) {
      console.log('dockerContainerName', this.dockerContainerName);
      console.log('dockerHostPath', this.dockerHostPath);
      console.log('dockerContainerPath', this.dockerContainerPath);
      console.log('dockerHostSslPath', this.dockerHostSslPath);
      console.log('dockerContainerSslPath', this.dockerContainerSslPath);
    }
  }

  private static convertPath(filePath: string, toHost: boolean = false): string {
    if (!this.isDockerized) {
      //需要判断是否是绝对路径
      if (path.isAbsolute(filePath)) {
        return filePath;
      }else{
        return path.join(this.getCwd(), filePath);
      }
    }

    if (toHost) {
      // 将容器内路径转换为宿主机路径
      return filePath.replace(
        new RegExp(`^${this.dockerContainerPath}`),
        this.dockerHostPath
      );
    } else {
      // 将宿主机路径转换为容器内路径
      return filePath.replace(
        new RegExp(`^${this.dockerHostPath}`),
        this.dockerContainerPath
      );
    }
  }

  // 处理日志配置的辅助函数
  private static parseLogDirective(line: string): string | 'off' | undefined {
    const match = line.match(/^(?:access_log|error_log)\s+([^;]+);/);
    if (match) {
      const params = match[1].trim().split(/\s+/);
      return params[0] === 'off' ? 'off' : params[0];
    }
    return undefined;
  }

  // 解析配置文件内容
  private static parseConfig(content: string): NginxConfig {
    const config: NginxConfig = {
      servers: [],
      upstreams: [],
      http: {}
    };

    const lines = content.split('\n');
    let currentServer: ServerConfig | null = null;
    let currentLocation: LocationConfig | null = null;
    let currentUpstream: UpstreamConfig | null = null;
    let inServerBlock = false;
    let inLocationBlock = false;
    let inUpstreamBlock = false;
    let inHttpBlock = false;
    let inEventsBlock = false;
    let braceCount = 0;

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();
      if (!line || line.startsWith('#')) continue;

      // 处理大括号
      if (line.includes('{')) braceCount++;
      if (line.includes('}')) braceCount--;

      // 处理 events 块
      if (line.startsWith('events {')) {
        inEventsBlock = true;
        config.events = {};
        continue;
      }

      // 处理 http 块
      if (line.startsWith('http {')) {
        inHttpBlock = true;
        config.http = {};
        continue;
      }

      // 处理 server 块
      if (line.startsWith('server {') || line === 'server{') {
        currentServer = {
          listen: [],
          server_name: [],
          locations: [],
          ssl: false
        };
        inServerBlock = true;
        config.servers.push(currentServer);
        continue;
      }

      // 处理 upstream 块
      if (line.startsWith('upstream ')) {
        const upstreamMatch = line.match(/upstream\s+([^\s{]+)\s*{/);
        if (upstreamMatch) {
          currentUpstream = {
            name: upstreamMatch[1],
            servers: []
          };
          inUpstreamBlock = true;
          config.upstreams.push(currentUpstream);
        }
        continue;
      }

      // 处理 location 块
      if (inServerBlock && currentServer && line.startsWith('location ')) {
        const locationMatch = line.match(/location\s+(?:([=~*^@]+)\s+)?([^\s{]+)\s*{/);
        if (locationMatch) {
          currentLocation = {
            path: locationMatch[2],
            modifier: locationMatch[1] || '',
            proxy_pass: '',
            root: '',
            index: []
          };
          inLocationBlock = true;
          currentServer.locations.push(currentLocation);
        }
        continue;
      }

      // 处理全局指令
      if (!inHttpBlock && !inEventsBlock && !inServerBlock && !inLocationBlock && !inUpstreamBlock) {
        if (line.startsWith('worker_processes ')) {
          config.worker_processes = line.replace('worker_processes', '').trim().replace(';', '');
        } else if (line.startsWith('pid ')) {
          config.pid = line.replace('pid', '').trim().replace(';', '');
        } else if (line.startsWith('user ')) {
          config.user = line.replace('user', '').trim().replace(';', '');
        } else if (line.startsWith('error_log ')) {
          const logValue = this.parseLogDirective(line);
          if (logValue) {
            config.error_log = logValue;
          }
        }
      }

      // 处理 events 块内的指令
      if (inEventsBlock && !inHttpBlock && config.events) {
        if (line.startsWith('worker_connections ')) {
          config.events.worker_connections = parseInt(
            line.replace('worker_connections', '').trim().replace(';', '')
          );
        }
      }

      // 处理 http 块内的指令
      if (inHttpBlock && !inServerBlock && !inLocationBlock && !inUpstreamBlock && config.http) {
        if (line.startsWith('include ')) {
          const match = line.match(/include\s+([^;]+);/);
          if (match) {
            if (!config.http.include) config.http.include = [];
            config.http.include.push(match[1].trim());
          }
        } else if (line.startsWith('default_type ')) {
          config.http.default_type = line.replace('default_type', '').trim().replace(';', '');
        } else if (line.startsWith('charset ')) {
          config.http.charset = line.replace('charset', '').trim().replace(';', '');
        } else if (line.startsWith('sendfile ')) {
          config.http.sendfile = line.replace('sendfile', '').trim().replace(';', '');
        } else if (line.startsWith('keepalive_timeout ')) {
          config.http.keepalive_timeout = parseInt(
            line.replace('keepalive_timeout', '').trim().replace(';', '')
          );
        } else if (line.startsWith('gzip ')) {
          config.http.gzip = line.replace('gzip', '').trim().replace(';', '');
        } else if (line.startsWith('gzip_static ')) {
          config.http.gzip_static = line.replace('gzip_static', '').trim().replace(';', '');
        } else if (line.startsWith('gzip_comp_level ')) {
          config.http.gzip_comp_level = parseInt(
            line.replace('gzip_comp_level', '').trim().replace(';', '')
          );
        } else if (line.startsWith('gzip_min_length ')) {
          config.http.gzip_min_length = parseInt(
            line.replace('gzip_min_length', '').trim().replace(';', '')
          );
        } else if (line.startsWith('gzip_types ')) {
          config.http.gzip_types = line
            .replace('gzip_types', '')
            .trim()
            .replace(';', '')
            .split(/\s+/);
        }
      }

      // 处理 server 块内的指令
      if (inServerBlock && currentServer && !inLocationBlock) {
        if (line.startsWith('listen ')) {
          const listenMatch = line.match(/listen\s+([^;]+);/);
          if (listenMatch) {
            currentServer.listen.push(parseInt(listenMatch[1].trim()));
          }
        } else if (line.startsWith('server_name ')) {
          const serverNameMatch = line.match(/server_name\s+([^;]+);/);
          if (serverNameMatch) {
            currentServer.server_name = serverNameMatch[1]
              .trim()
              .split(/\s+/)
              .map(name => name.trim());
          }
        } else if (line.startsWith('root ')) {
          const rootMatch = line.match(/root\s+([^;]+);/);
          if (rootMatch) {
            currentServer.root = rootMatch[1].trim();
          }
        } else if (line.startsWith('access_log ')) {
          const logValue = this.parseLogDirective(line);
          if (logValue) {
            currentServer.access_log = logValue;
          }
        } else if (line.startsWith('error_log ')) {
          const logValue = this.parseLogDirective(line);
          if (logValue) {
            currentServer.error_log = logValue;
          }
        } else if (line.startsWith('ssl_certificate ')) {
          currentServer.ssl_certificate = line
            .replace('ssl_certificate', '')
            .trim()
            .replace(';', '');
          currentServer.ssl = true;
        } else if (line.startsWith('ssl_certificate_key ')) {
          currentServer.ssl_certificate_key = line
            .replace('ssl_certificate_key', '')
            .trim()
            .replace(';', '');
          currentServer.ssl = true;
        } else if (line.startsWith('ssl_session_timeout ')) {
          currentServer.ssl_session_timeout = line
            .replace('ssl_session_timeout', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('ssl_ciphers ')) {
          currentServer.ssl_ciphers = line
            .replace('ssl_ciphers', '')
            .trim()
            .replace(';', '')
            .trim();
        } else if (line.startsWith('ssl_protocols ')) {
          currentServer.ssl_protocols = line
            .replace('ssl_protocols', '')
            .trim()
            .replace(';', '')
            .trim();
        } else if (line.startsWith('ssl_prefer_server_ciphers ')) {
          currentServer.ssl_prefer_server_ciphers = line.includes('on');
          currentServer.ssl = true;
        } else if (line.startsWith('error_page ')) {
          if (!currentServer.error_page) {
            currentServer.error_page = {};
          }
          const errorMatch = line.match(/error_page\s+([^\s]+)\s+([^;]+);/);
          if (errorMatch) {
            const codes = errorMatch[1].split(/\s+/);
            const page = errorMatch[2];
            codes.forEach(code => {
              currentServer!.error_page![code] = page;
            });
          }
        } else if (line.startsWith('include ')) {
          if (!currentServer.includes) {
            currentServer.includes = [];
          }
          const includeMatch = line.match(/include\s+([^;]+);/);
          if (includeMatch) {
            currentServer.includes.push(includeMatch[1].trim());
          }
        } else if (line.startsWith('return ')) {
          const returnMatch = line.match(/return\s+(\d+)\s+([^;]+);/);
          if (returnMatch) {
            currentServer.return = {
              code: parseInt(returnMatch[1]),
              url: returnMatch[2].trim().replace(/['"]/g, '') // 移除可能的引号
            };
          }
        } else if (line.startsWith('rewrite ')) {
          if (!currentServer.rewrites) {
            currentServer.rewrites = [];
          }
          const rewriteMatch = line.match(/rewrite\s+([^\s]+)\s+([^\s;]+)(?:\s+([^\s;]+))?\s*;/);
          if (rewriteMatch) {
            currentServer.rewrites.push({
              pattern: rewriteMatch[1],
              replacement: rewriteMatch[2],
              flag: rewriteMatch[3]
            });
          }
        }

      }

      // 处理 location 块内的指令
      if (inLocationBlock && currentLocation) {
        if (line.startsWith('proxy_pass ')) {
          const proxyPassMatch = line.match(/proxy_pass\s+([^;]+);/);
          if (proxyPassMatch) {
            currentLocation.proxy_pass = proxyPassMatch[1].trim();
          }
        } else if (line.startsWith('root ')) {
          const rootMatch = line.match(/root\s+([^;]+);/);
          if (rootMatch) {
            currentLocation.root = rootMatch[1].trim();
          }
        } else if (line.startsWith('index ')) {
          const indexMatch = line.match(/index\s+([^;]+);/);
          if (indexMatch) {
            currentLocation.index = indexMatch[1]
              .trim()
              .split(/\s+/)
              .map(index => index.trim());
          }
        } else if (line.startsWith('access_log ')) {
          const logValue = this.parseLogDirective(line);
          if (logValue) {
            currentLocation.access_log = logValue;
          }
        } else if (line.startsWith('error_log ')) {
          const logValue = this.parseLogDirective(line);
          if (logValue) {
            currentLocation.error_log = logValue;
          }
        } else if (line.startsWith('proxy_set_header ')) {
          if (!currentLocation.proxy_headers) {
            currentLocation.proxy_headers = [];
          }
          const headerMatch = line.match(/proxy_set_header\s+([^\s]+)\s+([^;]+);/);
          if (headerMatch) {
            currentLocation.proxy_headers.push({
              name: headerMatch[1],
              value: headerMatch[2]
            });
          }
        } else if (line.startsWith('proxy_connect_timeout ')) {
          currentLocation.proxy_connect_timeout = line
            .replace('proxy_connect_timeout', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('proxy_read_timeout ')) {
          currentLocation.proxy_read_timeout = line
            .replace('proxy_read_timeout', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('proxy_send_timeout ')) {
          currentLocation.proxy_send_timeout = line
            .replace('proxy_send_timeout', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('proxy_buffer_size ')) {
          currentLocation.proxy_buffer_size = line
            .replace('proxy_buffer_size', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('proxy_buffers ')) {
          currentLocation.proxy_buffers = line
            .replace('proxy_buffers', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('proxy_busy_buffers_size ')) {
          currentLocation.proxy_busy_buffers_size = line
            .replace('proxy_busy_buffers_size', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('client_max_body_size ')) {
          currentLocation.client_max_body_size = line
            .replace('client_max_body_size', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('client_body_buffer_size ')) {
          currentLocation.client_body_buffer_size = line
            .replace('client_body_buffer_size', '')
            .trim()
            .replace(';', '');
        } else if (line.startsWith('include ')) {
          if (!currentLocation.includes) {
            currentLocation.includes = [];
          }
          const includeMatch = line.match(/include\s+([^;]+);/);
          if (includeMatch) {
            currentLocation.includes.push(includeMatch[1].trim());
          }
        } else if (line.startsWith('add_header ')) {
          const addHeaderMatch = line.match(/add_header\s+([^;]+);/);
          if (addHeaderMatch) {
            const headerParts = addHeaderMatch[1].trim().split(/\s+/);
            const headerName = headerParts[0];
            const headerValue = headerParts.slice(1).join(' ').replace(/['"]/g, '');
            if (!currentLocation.add_header) {
              currentLocation.add_header = {};
            }
            currentLocation.add_header[headerName] = headerValue;
          }
        } else if (line.startsWith('try_files ')) {
          const tryFilesMatch = line.match(/try_files\s+([^;]+);/);
          if (tryFilesMatch) {
            currentLocation.try_files = tryFilesMatch[1]
              .trim()
              .split(/\s+/)
              .map(file => file.trim());
          }
        } else if (line.startsWith('return ')) {
          const returnMatch = line.match(/return\s+(\d+)\s+([^;]+);/);
          if (returnMatch) {
            currentLocation.return = {
              code: parseInt(returnMatch[1]),
              url: returnMatch[2].trim().replace(/['"]/g, '') // 移除可能的引号
            };
          }
        } else if (line.startsWith('rewrite ')) {
          if (!currentLocation.rewrites) {
            currentLocation.rewrites = [];
          }
          const rewriteMatch = line.match(/rewrite\s+([^\s]+)\s+([^\s;]+)(?:\s+([^\s;]+))?\s*;/);
          if (rewriteMatch) {
            currentLocation.rewrites.push({
              pattern: rewriteMatch[1],
              replacement: rewriteMatch[2],
              flag: rewriteMatch[3]
            });
          }
        }
      }

      // 处理 upstream 块内的指令
      if (inUpstreamBlock && currentUpstream) {
        if (line.startsWith('server ')) {
          const serverMatch = line.match(/server\s+([^;]+);/);
          if (serverMatch) {
            const serverParams = serverMatch[1].split(/\s+/);
            const [address, ...options] = serverParams;
            
            const serverConfig: UpstreamServer = {
              address: address
            };
            
            // 解析其他选项
            options.forEach(option => {
              if (option.startsWith('weight=')) {
                serverConfig.weight = parseInt(option.split('=')[1]);
              } else if (option.startsWith('max_fails=')) {
                serverConfig.max_fails = parseInt(option.split('=')[1]);
              } else if (option.startsWith('fail_timeout=')) {
                serverConfig.fail_timeout = option.split('=')[1];
              } else if (option === 'backup') {
                serverConfig.backup = true;
              } else if (option === 'down') {
                serverConfig.down = true;
              }
            });
            
            currentUpstream.servers.push(serverConfig);
          }
        }
      }

      // 处理块的结束
      if (braceCount === 0) {
        if (inLocationBlock) {
          inLocationBlock = false;
          currentLocation = null;
        } else if (inServerBlock) {
          inServerBlock = false;
          currentServer = null;
        } else if (inUpstreamBlock) {
          inUpstreamBlock = false;
          currentUpstream = null;
        } else if (inHttpBlock) {
          inHttpBlock = false;
        } else if (inEventsBlock) {
          inEventsBlock = false;
        }
      }
    }

    return config;
  }

  static getCwd() : string {
    return this.isDockerized ? this.dockerHostPath : path.dirname(this.nginxExec);
  }

  // 获取所有Nginx配置
  static async getAllConfigs(): Promise<NginxConfigInfo[]> {
    try {
      console.log('getAllConfigs', this.isDockerized);

      let cmd = this.isDockerized
        ? `docker exec ${this.dockerContainerName} nginx -T`
        : `${this.nginxExec} -T`;
      let cwd = this.getCwd();
      const { stdout } = await execAsync(cmd, { cwd });
      
      // 解析配置文件内容
      const configs: NginxConfigInfo[] = [];
      const configBlocks = stdout.split(/^# configuration file/m);
      
    
      for (const block of configBlocks) {
        if (!block.trim()) continue;
        
        const [filePath, ...contentLines] = block.trim().split('\n');
        const content = contentLines.join('\n');
        console.log('filePath', filePath);
        // 转换路径为宿主机路径
        let hostFilePath = this.convertPath(filePath.trim(), true);
        console.log('hostFilePath', hostFilePath);
        hostFilePath = hostFilePath.substring(0, hostFilePath.lastIndexOf(':'));
        const config = this.parseConfig(content);

       

        configs.push({
          name: path.basename(hostFilePath),
          content,
          file_path: hostFilePath,
          servers: config.servers,
          upstreams: config.upstreams
        });
      }

   
      return configs;
    } catch (error) {
      console.error('获取 Nginx 配置失败:', error);
      throw error;
    }
  }

  // 获取主配置文件内容
  static async getMainConfig(): Promise<NginxConfigInfo | null> {
    const configs = await this.getAllConfigs();
    return configs.find(config => config.file_path.endsWith('nginx.conf')) || null;
  }

  // 读取证书文件并解析信息
  private static async parseCertificate(certPath: string): Promise<{
    notBefore: string;
    notAfter: string;
    issuer: string;
  }> {
    try {
      const certPem = await fs.promises.readFile(certPath, 'utf8');
      const cert = new crypto.X509Certificate(certPem);
      
      return {
        notBefore: cert.validFrom,
        notAfter: cert.validTo,
        issuer: cert.issuer
      };
    } catch (error) {
      console.error(`解析证书文件失败: ${certPath}`, error);
      throw error;
    }
  }

  // 获取所有SSL证书配置
  static async getSSLCertificates(): Promise<SSLCertInfo[]> {
    try {
      const configs = await this.getAllConfigs();
      const sslConfigs: SSLCertInfo[] = [];
      
      for (const config of configs) {
        // 遍历所有包含 SSL 配置的 server 块
        for (const server of config.servers) {
          if (server.ssl_certificate && server.ssl_certificate_key) {
            const sslConfig: SSLCertInfo = {
              domain: server.server_name[0] || 'unknown', // 使用第一个域名作为主域名
              cert_path: server.ssl_certificate,
              key_path: server.ssl_certificate_key,
              server_name: server.server_name,
              listen_port: server.listen[0] || 443,
              ssl_protocols: server.ssl_protocols,
              ssl_ciphers: server.ssl_ciphers,
              ssl_prefer_server_ciphers: server.ssl_prefer_server_ciphers,
              ssl_session_timeout: server.ssl_session_timeout,
              ssl_session_cache: undefined, // 暂不支持
              ssl_stapling: false, // 暂不支持
              ssl_stapling_verify: false, // 暂不支持
              ssl_trusted_certificate: undefined, // 暂不支持
              status: 'unknown' // 初始状态设为 unknown，后续检查证书文件来更新
            };
            sslConfigs.push(sslConfig);
          }
        }
      }

      // 检查证书文件并更新状态
      for (const cert of sslConfigs) {
        try {
          const certPath = this.convertSslPath(cert.cert_path, true);

          const certInfo = await this.parseCertificate(certPath);
          
          cert.not_before = new Date(certInfo.notBefore).toLocaleString('zh-CN');
          cert.not_after = new Date(certInfo.notAfter).toLocaleString('zh-CN');
          cert.issuer = certInfo.issuer;
          
          const now = new Date();
          const expireDate = new Date(certInfo.notAfter);
          cert.status = now <= expireDate ? 'valid' : 'expired';
        } catch (error) {
          console.error(`检查证书 ${cert.domain} 失败:`, error);
          cert.status = 'error';
        }
      }

      return sslConfigs;
    } catch (error) {
      console.error('获取SSL证书配置失败:', error);
      throw error;
    }
  }

  // 验证Nginx配置
  static async testConfig(): Promise<boolean> {
    if (this.isDockerized) {
      await execAsync(`docker exec ${this.dockerContainerName} nginx -t`);
    } else {
      await execAsync(`${this.nginxExec} -t`, { cwd: this.getCwd() });
    }
    return true;
  }

  // 重新加载Nginx配置
  static async reloadConfig(): Promise<void> {
    try {
      if (this.isDockerized) {
        await execAsync(`docker exec ${this.dockerContainerName} nginx -s reload`);
      } else {
        await execAsync(this.nginxReloadCmd, { cwd: this.getCwd() });
      }
    } catch (error) {
      console.error('重载 Nginx 配置失败:', error);
      throw error;
    }
  }

  // 获取所有日志文件路径
  static async getAllLogPaths(): Promise<Set<string>> {
    try {
      const logPaths = new Set<string>();
      const configs = await this.getAllConfigs();

      for (const config of configs) {
        const lines = config.content.split('\n');
        for (const line of lines) {
          const trimmedLine = line.trim();
          if (!trimmedLine || trimmedLine.startsWith('#')) continue;

          if (trimmedLine.startsWith('access_log ') || trimmedLine.startsWith('error_log ')) {
            const logValue = this.parseLogDirective(trimmedLine);
            if (logValue && logValue !== 'off') {
              logPaths.add(this.convertLogPath(logValue, true));
            }
          }
        }
      }

      return logPaths;
    } catch (error) {
      console.error('获取日志路径失败:', error);
      throw error;
    }
  }

  private static convertLogPath(logPath: string, toHost: boolean = false): string {
    if (this.isDockerized) {
      console.log('convertLogPath', logPath);
      console.log('dockerContainerLogPath', this.dockerContainerLogPath);
      console.log('dockerHostLogPath', this.dockerHostLogPath);
      return logPath.replace(this.dockerContainerLogPath, this.dockerHostLogPath);
    }
    //判断是否绝对路径
    if (path.isAbsolute(logPath)) {
      return logPath;
    }else{
      return path.join(this.getCwd(), logPath);
    }

  }

  private static convertSslPath(sslPath: string, toHost: boolean = false): string {
    if (this.isDockerized) {
      return sslPath.replace(this.dockerContainerSslPath, this.dockerHostSslPath);
    }
    if(path.isAbsolute(sslPath)){
      return sslPath;
    }else{
      return path.join(this.getCwd(), sslPath);
    }
  }

  // 下载证书文件
  static async downloadCertificate(domain: string): Promise<{ filePath: string; cleanup: () => void }> {
    try {
      const configs = await this.getAllConfigs();
      let certConfig: SSLCertInfo | null = null;

      // 查找对应域名的证书配置
      for (const config of configs) {
        for (const server of config.servers) {
          if (server.ssl_certificate && server.ssl_certificate_key && server.server_name.includes(domain)) {
            certConfig = {
              domain,
              cert_path: this.convertSslPath(server.ssl_certificate, true),
              key_path: this.convertSslPath(server.ssl_certificate_key, true),
              server_name: server.server_name,
              listen_port: server.listen[0] || 443,
              status: 'unknown'
            };
            break;
          }
        }
        if (certConfig) break;
      }

      if (!certConfig) {
        throw new Error(`未找到域名 ${domain} 的证书配置`);
      }

      // 创建临时目录
      const tmpDir = path.join(process.cwd(), 'tmp');
      if (!fs.existsSync(tmpDir)) {
        fs.mkdirSync(tmpDir);
      }

      // 创建 zip 文件
      const zipFileName = `${domain}_cert_${Date.now()}.zip`;
      const zipFilePath = path.join(tmpDir, zipFileName);
      const output = fs.createWriteStream(zipFilePath);
      const archive = archiver('zip', {
        zlib: { level: 9 } // 设置压缩级别
      });

      // 监听错误
      output.on('error', (err) => {
        throw err;
      });

      // 管道连接
      archive.pipe(output);

      // 添加证书文件
      archive.file(certConfig.cert_path, { name: path.basename(certConfig.cert_path) });
      archive.file(certConfig.key_path, { name: path.basename(certConfig.key_path) });

      // 添加 README 文件
      const readmeContent = `SSL Certificate for ${domain}
Generated at: ${new Date().toLocaleString('zh-CN')}
Server Names: ${certConfig.server_name.join(', ')}
Listen Port: ${certConfig.listen_port}

Files:
- ${path.basename(certConfig.cert_path)}: SSL Certificate
- ${path.basename(certConfig.key_path)}: Private Key
`;
      archive.append(readmeContent, { name: 'README.txt' });

      // 完成打包
      await archive.finalize();

      // 返回文件路径和清理函数
      return {
        filePath: zipFilePath,
        cleanup: () => {
          try {
            fs.unlinkSync(zipFilePath);
            if (fs.readdirSync(tmpDir).length === 0) {
              fs.rmdirSync(tmpDir);
            }
          } catch (error) {
            console.error('清理临时文件失败:', error);
          }
        }
      };
    } catch (error) {
      console.error('下载证书失败:', error);
      throw error;
    }
  }
} 